<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@1.11.1/dist/jquery.min.js"></script>
    <style>
        #sent_sms_btn{
            background-color: #efefef
        }
    </style>
</head>
<body>
<h2>登录页面 JWT</h2>
<h3>表单登录</h3>
<h5>通过 查看控制台日志或POSTMAN等工具 来了解 JWT 流程.</h5>
<h5>application.yml -> ums.jwt.blacklist.enable = false , 此时为 jwt + session(jwtToken 缓存 redis 模式)</h5>
<h5>如果要调试 纯 jwt 模式, 请设置 application.yml -> ums.jwt.blacklist.enable = true</h5>
<!-- 通过 th:action 的方式支持 csrf 或者 添加隐藏域<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> -->
<form id="reg-form" th:action="@{/authentication/form}" method="post">
    <table>
        <tr>
            <td>用户名：</td>
            <td><input type="text" name="username" value="admin" ><p style="color: #ff0000"
                                                                           id="error-name"></p></td>
        </tr>
        <tr>
            <td>密码：</td>
            <td><input type="password" name="password" value="admin"></td>
        </tr>
        <tr>
            <td>图形验证码：</td>
            <td>
                <input type="text" name="imageCode">
                <img class="img" th:src="@{/code/image}" style="width: 67px; height: 23px">
            </td>
        </tr>
        <tr>
            <td ><input type="checkbox" name="rememberMe" checked="true">记住我</input></td>
            <td><p style="color: #ff0000" id="error-code"></p></td>
        </tr>
        <tr>
            <td ><button id="btn-reg" type="button">登录ajax</button></td>
        </tr>
    </table>
</form>

<br>
<h1>先登录获取 jwt 与 refreshToken, 看控制台打印日志</h1>
<h5>通过设置 application.yml -> ums.jwt.blacklist 下的参数控制 jwt 传递方式</h5>
<h5>通过 refreshToken 刷新 jwt 时, 默认 oldJwt 有效期没在 ums.jwt.remainingRefreshInterval 的时间内, 原样返回 oldJwt</h5>
<h5>如果想重新刷新 jwt 则通过设置 ums.jwt.alwaysRefresh=true, 这样每次通过 refreshToken 刷新 jwt 则总是返回 newJwt</h5>
<form id="refresh-token" th:action="@{/jwt/refreshToken}" method="post">
    <tr>
        <td ><button id="btn-ref" type="button">通过 refresh 获取 Jwt</button></td>
    </tr>

</form>
<br><br>
<dev id="basePath" th:basePath="@{/}" style="display: none"/>
</body>
<script>
    var basePath = $("#basePath").attr("basePath");

    console.log("========== Authorization: 清除 缓存到本地缓存的 JWT ============")
    console.log("")
    window.localStorage.setItem('jwt', "");

    $.fn.serializeObject = function()
    {
        let o = {};
        let a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name]) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    }

    $(".img").click(function(){
        let uri = this.getAttribute("src");
        console.log(uri)
        let end = uri.indexOf('?', 0);
        console.log(end)
        if (end === -1) {
            uri = uri + '?'+ Math.random();
        } else {
            uri = uri.substring(0, end) + '?'+ Math.random();
        }
        console.log(uri)
        this.setAttribute('src', uri);
    });

    $("#btn-ref").click(function(){
        let url = $("#refresh-token").attr("action");
        let refreshToken = window.localStorage.getItem('refresh_token');
        if (undefined === refreshToken || null === refreshToken) {
            refreshToken = "";
        }
        console.log("refreshtoken: " + refreshToken);
        // 刷新 JWT
        $.ajax({
            url: url,
            type: "POST",
            dataType: "json",
            contentType: 'application/json; charset=UTF-8',
            headers: {
                'refresh_token': refreshToken
            },
            beforeSend: function(request) {
                // 与 headers 重复
                // 如果 jwt 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求头 中
                let jwt = window.localStorage.getItem('jwt')
                if (undefined !== jwt && null !== jwt) {
                    console.log("========== 访问需要权限的 API: JWT 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求头 中 ============")
                    console.log("JWT 设置到 请求头 Authorization : " + jwt);
                    console.log("")
                    request.setRequestHeader("Authorization", jwt);
                }
            },
            success: function (data) {
                console.log("==========通过 refreshToken 刷新 jwt 成功============")
                // 成功
                // ...
                console.log(data)

            },
            error: function (data) {
                // 失败
                console.log("********通过 refreshToken 刷新 jwt 失败*********")
                console.log(data)
            },
            complete: function (xhr, data) {
                console.log("========== 刷新 jwt 成功: 设置 jwt 到本地缓存 ============")
                console.log("========== 通过 响应头 获取 JWT ============")
                let accessToken;
                //  jwt 传输的方式是 ums.jwt.bearer.bearerTokenHeaderName 方式
                let Authorization = xhr.getResponseHeader('Authorization');
                console.log('Authorization: ' + Authorization);
                console.log("")

                if (undefined !== Authorization && null === Authorization) {
                    // jwt 传输的方式是 ums.jwt.bearer.bearerTokenHeaderName 方式
                    console.log("========== 通过 响应体 获取 JWT ============")
                    accessToken = xhr.responseJSON.data.token;
                    console.log('accessToken: ' + accessToken);
                    console.log("")
                    if (undefined !== accessToken && null !== accessToken) {
                        console.log("========== accessToken: JWT 缓存到本地缓存 ============")
                        window.localStorage.setItem('jwt', accessToken);
                    }

                } else {
                    console.log("========== Authorization: JWT 缓存到本地缓存 ============")
                    console.log("")
                    window.localStorage.setItem('jwt', Authorization);
                }
            }
        })
        console.log("==========通过 refreshToken 刷新 jwt 流程结束============")
        return
    });

    function submitFormByAjax(url, formId, errorNameId, errorCodeId, imgId) {
        return function () {
            let targetUrl;
            let ajaxData;
            ajaxData = JSON.stringify($(formId).serializeObject())
            console.log(ajaxData)

            console.log("========== 登录并获取 JWT ============")
            // 登录并获取 JWT
            $.ajax({
                url: url,
                data: ajaxData,
                type: "POST",
                dataType: "json",
                contentType: 'application/json; charset=UTF-8',
                success: function (data) {
                    $(errorNameId).text("")
                    $(errorCodeId).text("")
                    console.log("==========注册成功============")
                    // 注册成功
                    // ...
                    console.log(data)
                    let uri = data.data.targetUrl
                    if (uri === null) {
                        uri = basePath
                    }
                    console.log('targetUrl: ' + uri);

                    targetUrl = uri;

                },
                error: function (data) {
                    // 注册失败
                    $(errorNameId).text("")
                    $(errorCodeId).text("")
                    console.log("********注册失败*********")
                    console.log(data)
                    data = data.responseJSON
                    if (undefined !== data) {
                        console.log(data);
                        // 错误代码看ErrorCodeEnum
                        if (data.code >= 900 && data.code < 1000) {
                            $(errorNameId).text(data.msg)
                        } else if (data.code >= 600 && data.code < 700) {
                            $(errorCodeId).text(data.msg)
                        }
                    }
                    $(imgId).trigger("click")
                },
                complete: function (xhr, data) {
                    let accessToken;
                    let Authorization;
                    let refresh_token;
                    /*
                        认证成功: 设置 jwt 到本地缓存
                    */
                    if (xhr.status === 200) {
                        console.log("========== 认证成功: 设置 jwt 到本地缓存 ============")
                        console.log("========== 通过 响应头 获取 JWT ============")
                        //  jwt 传输的方式是 ums.jwt.bearer.bearerTokenHeaderName 方式
                        Authorization = xhr.getResponseHeader('Authorization');
                        console.log('Authorization: ' + Authorization);
                        console.log("")
                        console.log("========== 通过 响应头 获取 refresh_token ============")
                        //  jwt 传输的方式是 ums.jwt.bearer.bearerTokenHeaderName 方式
                        refresh_token = xhr.getResponseHeader('refresh_token');
                        console.log('refresh_token: ' + refresh_token);
                        console.log("")

                        if (undefined !== Authorization && null === Authorization) {
                            // jwt 传输的方式是 ums.jwt.bearer.bearerTokenHeaderName 方式
                            console.log("========== 通过 响应体 获取 JWT ============")
                            accessToken = xhr.responseJSON.data.token;
                            console.log('accessToken: ' + accessToken);
                            console.log("")
                            if (undefined !== accessToken && null !== accessToken) {
                                console.log("========== accessToken: JWT 缓存到本地缓存 ============")
                                window.localStorage.setItem('jwt', accessToken);
                            }

                        } else {
                            console.log("========== Authorization: JWT 缓存到本地缓存 ============")
                            console.log("")
                            window.localStorage.setItem('jwt', Authorization);
                            if (undefined !== refresh_token && null !== refresh_token) {
                                console.log("========== refresh_token: refresh_token 缓存到本地缓存 ============")
                                window.localStorage.setItem('refresh_token', refresh_token);
                            }
                        }

                        // 如果 jwt 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求体 中
                        if (undefined !== accessToken && null !== accessToken) {
                            // 添加 JWT 到 body 参数
                            let jwt = window.localStorage.getItem('jwt');
                            if (undefined !== jwt && null !== jwt) {
                                console.log("========== 访问需要权限的 API: JWT 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求体 中 ============")
                                ajaxData = '{"access_token":"' + jwt + '"}'
                                console.log("JWT 设置到 body 的 access_token : " + ajaxData);
                                console.log("")
                            } else {
                                ajaxData = null;
                            }
                        } else {
                            ajaxData = null;
                        }
                    }

                    console.log("targetUrl: " + targetUrl);
                    console.log(ajaxData)

                    $.ajax({
                        // 如果用的是模板，则 url 可以使用注入的方式，会跟着配置动态改变
                        url: targetUrl,
                        type: "POST",
                        data: ajaxData,
                        dataType: "json",
                        contentType: 'application/json; charset=UTF-8',
                        headers: {
                            // 'Authorization': window.localStorage.getItem('jwt')
                        },
                        beforeSend: function(request) {
                            // 与 headers 重复
                            // 如果 jwt 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求头 中
                            let jwt = window.localStorage.getItem('jwt')
                            if (undefined !== jwt && null !== jwt) {
                                console.log("========== 访问需要权限的 API: JWT 传输的方式是 ums.jwt.bearer.bearerTokenParameterName 方式, 则设置到 请求头 中 ============")
                                console.log("JWT 设置到 请求头 Authorization : " + jwt);
                                console.log("")
                                request.setRequestHeader("Authorization", jwt);
                            }
                        },
                        success: function (data) {
                            console.log("--------> 获取 /me 数据 成功")
                            console.log(data)
                            console.log()
                        },
                        error: function (data) {
                            console.log("........> 获取 /me 数据 错误")
                            console.log(data)
                            console.log()
                        },
                        complete: function (xhr, data) {
                            /*
                               如果 JWT 刷新策略是 JwtRefreshHandlerPolicy.AUTO_RENEW, 则后自动刷新 JWT,
                               如果刷新只会从 header 传输, 更新本地 JWT 缓存.
                            */
                            let Authorization = xhr.getResponseHeader('Authorization');
                            console.log(Authorization);
                            let oldJwt =  window.localStorage.getItem('jwt');
                            // 刷新 jwt, 重新设置
                            if (undefined !== Authorization && null !== Authorization && oldJwt !== Authorization) {
                                console.log("========> 如果 JWT 刷新策略是 JwtRefreshHandlerPolicy.AUTO_RENEW, 则后自动刷新 JWT,\n" +
                                    "                               如果刷新只会从 header 传输, 更新本地 JWT 缓存.")
                                window.localStorage.setItem('jwt', Authorization);
                                console.log("")
                            }
                        }
                    });
                }
            })
            return
        };
    }


    $("#btn-mobile").click(
        submitFormByAjax($("#mobile-form").attr("action"), "#mobile-form", "#error-name-mobile", "#error-code-mobile", ".img-mobile")
    )


    $("#btn-reg").click(
        submitFormByAjax($("#reg-form").attr("action"), "#reg-form", "#error-name", "#error-code", ".img")
    )
</script>
</html>